package com.zenithmind.library.controller;

import com.zenithmind.common.result.PageResult;
import com.zenithmind.common.result.Result;
import com.zenithmind.library.pojo.dto.ReservationCreateDTO;
import com.zenithmind.library.pojo.dto.ReservationUpdateDTO;
import com.zenithmind.library.pojo.query.ReservationQuery;
import com.zenithmind.library.pojo.vo.ReservationVO;
import com.zenithmind.library.service.ReservationService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.validation.Valid;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.*;

import java.time.LocalDate;
import java.util.List;

/**
 * 预约管理控制器
 * 
 * @author ZenithMind
 * @since 2024-06-14
 */
@Slf4j
@RestController
@RequestMapping("/api/zenithMind/v1/reservations")
@RequiredArgsConstructor
@Tag(name = "预约管理", description = "图书预约、取消、取书等操作")
public class ReservationController {

    private final ReservationService reservationService;

    @PostMapping
    @Operation(summary = "创建预约", description = "用户预约图书")
    @PreAuthorize("hasAuthority('library:reservation:create')")
    public Result<ReservationVO> createReservation(@Valid @RequestBody ReservationCreateDTO createDTO) {
        log.info("创建预约，数据：{}", createDTO);
        return reservationService.createReservation(createDTO);
    }

    @PutMapping("/{id}")
    @Operation(summary = "更新预约", description = "更新预约信息")
    @PreAuthorize("hasAuthority('library:reservation:update')")
    public Result<ReservationVO> updateReservation(
            @Parameter(description = "预约ID", required = true) @PathVariable String id,
            @Valid @RequestBody ReservationUpdateDTO updateDTO) {
        log.info("更新预约，ID：{}，数据：{}", id, updateDTO);
        return reservationService.updateReservation(id, updateDTO);
    }

    @PostMapping("/{id}/cancel")
    @Operation(summary = "取消预约", description = "用户取消预约")
    @PreAuthorize("hasAuthority('library:reservation:update')")
    public Result<Void> cancelReservation(
            @Parameter(description = "预约ID", required = true) @PathVariable String id,
            @Parameter(description = "取消原因") @RequestParam(required = false) String reason) {
        log.info("取消预约，ID：{}，原因：{}", id, reason);
        return reservationService.cancelReservation(id, reason);
    }

    @PostMapping("/{id}/pickup")
    @Operation(summary = "确认取书", description = "确认用户已取书")
    @PreAuthorize("hasAuthority('library:reservation:update')")
    public Result<Void> confirmPickup(
            @Parameter(description = "预约ID", required = true) @PathVariable String id) {
        log.info("确认取书，预约ID：{}", id);
        return reservationService.confirmPickup(id);
    }

    @GetMapping
    @Operation(summary = "分页查询预约记录", description = "根据条件分页查询预约记录")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<PageResult<ReservationVO>> getReservationPage(@Valid ReservationQuery query) {
        log.info("分页查询预约记录，查询条件：{}", query);
        PageResult<ReservationVO> result = reservationService.getReservationPage(query);
        return Result.success(result);
    }

    @GetMapping("/user/{userId}")
    @Operation(summary = "查询用户预约记录", description = "根据用户ID查询预约记录")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<PageResult<ReservationVO>> getReservationsByUser(
            @Parameter(description = "用户ID", required = true) @PathVariable String userId,
            @Valid ReservationQuery query) {
        log.info("查询用户预约记录，用户ID：{}，查询条件：{}", userId, query);
        PageResult<ReservationVO> result = reservationService.getReservationsByUser(userId, query);
        return Result.success(result);
    }

    @GetMapping("/book/{bookId}")
    @Operation(summary = "查询图书预约记录", description = "根据图书ID查询预约记录")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<PageResult<ReservationVO>> getReservationsByBook(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId,
            @Valid ReservationQuery query) {
        log.info("查询图书预约记录，图书ID：{}，查询条件：{}", bookId, query);
        PageResult<ReservationVO> result = reservationService.getReservationsByBook(bookId, query);
        return Result.success(result);
    }

    @GetMapping("/user/{userId}/current")
    @Operation(summary = "查询用户当前预约", description = "查询用户当前的预约记录")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<List<ReservationVO>> getCurrentReservationsByUser(
            @Parameter(description = "用户ID", required = true) @PathVariable String userId) {
        log.info("查询用户当前预约，用户ID：{}", userId);
        List<ReservationVO> result = reservationService.getCurrentReservationsByUser(userId);
        return Result.success(result);
    }

    @GetMapping("/book/{bookId}/queue")
    @Operation(summary = "查询图书预约队列", description = "查询图书的预约队列")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<List<ReservationVO>> getBookReservationQueue(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId) {
        log.info("查询图书预约队列，图书ID：{}", bookId);
        List<ReservationVO> result = reservationService.getBookReservationQueue(bookId);
        return Result.success(result);
    }

    @GetMapping("/available")
    @Operation(summary = "查询可取书预约", description = "查询可取书的预约记录")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<PageResult<ReservationVO>> getAvailableReservations(@Valid ReservationQuery query) {
        log.info("查询可取书预约，查询条件：{}", query);
        PageResult<ReservationVO> result = reservationService.getAvailableReservations(query);
        return Result.success(result);
    }

    @GetMapping("/expired")
    @Operation(summary = "查询过期预约", description = "查询过期的预约记录")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<PageResult<ReservationVO>> getExpiredReservations(@Valid ReservationQuery query) {
        log.info("查询过期预约，查询条件：{}", query);
        PageResult<ReservationVO> result = reservationService.getExpiredReservations(query);
        return Result.success(result);
    }

    @GetMapping("/check/user/{userId}/book/{bookId}")
    @Operation(summary = "检查用户是否可以预约", description = "检查用户是否可以预约指定图书")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<Boolean> canUserReserve(
            @Parameter(description = "用户ID", required = true) @PathVariable String userId,
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId) {
        log.info("检查用户是否可以预约，用户ID：{}，图书ID：{}", userId, bookId);
        return reservationService.canUserReserve(userId, bookId);
    }

    @GetMapping("/check/book/{bookId}")
    @Operation(summary = "检查图书是否可以预约", description = "检查图书是否可以被预约")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<Boolean> canBookBeReserved(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId) {
        log.info("检查图书是否可以预约，图书ID：{}", bookId);
        return reservationService.canBookBeReserved(bookId);
    }

    @PostMapping("/book/{bookId}/return-notification")
    @Operation(summary = "处理图书归还通知", description = "处理图书归还后的预约通知")
    @PreAuthorize("hasAuthority('library:reservation:update')")
    public Result<Void> processBookReturnNotification(
            @Parameter(description = "图书ID", required = true) @PathVariable String bookId) {
        log.info("处理图书归还通知，图书ID：{}", bookId);
        return reservationService.processBookReturnNotification(bookId);
    }

    @PostMapping("/{id}/notification")
    @Operation(summary = "发送预约通知", description = "发送预约通知给用户")
    @PreAuthorize("hasAuthority('library:reservation:update')")
    public Result<Void> sendReservationNotification(
            @Parameter(description = "预约ID", required = true) @PathVariable String id) {
        log.info("发送预约通知，预约ID：{}", id);
        return reservationService.sendReservationNotification(id);
    }

    @PostMapping("/batch-notification")
    @Operation(summary = "批量发送预约通知", description = "批量发送预约通知")
    @PreAuthorize("hasAuthority('library:reservation:update')")
    public Result<Integer> batchSendReservationNotifications() {
        log.info("批量发送预约通知");
        return reservationService.batchSendReservationNotifications();
    }

    @PostMapping("/auto-process-expired")
    @Operation(summary = "自动处理过期预约", description = "自动处理过期的预约记录")
    @PreAuthorize("hasAuthority('library:reservation:update')")
    public Result<Integer> autoProcessExpiredReservations() {
        log.info("自动处理过期预约");
        return reservationService.autoProcessExpiredReservations();
    }

    @GetMapping("/statistics")
    @Operation(summary = "获取预约统计", description = "获取预约统计信息")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<ReservationVO> getReservationStatistics(
            @Parameter(description = "开始日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate) {
        log.info("获取预约统计，开始日期：{}，结束日期：{}", startDate, endDate);
        
        if (startDate == null) {
            startDate = LocalDate.now().minusMonths(1);
        }
        if (endDate == null) {
            endDate = LocalDate.now();
        }
        
        ReservationVO result = reservationService.getReservationStatistics(startDate, endDate);
        return Result.success(result);
    }

    @GetMapping("/hot-books")
    @Operation(summary = "获取热门预约图书", description = "获取热门预约图书列表")
    @PreAuthorize("hasAuthority('library:reservation:query')")
    public Result<List<ReservationVO>> getHotReservedBooks(
            @Parameter(description = "开始日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate startDate,
            @Parameter(description = "结束日期") @RequestParam(required = false) 
            @DateTimeFormat(pattern = "yyyy-MM-dd") LocalDate endDate,
            @Parameter(description = "限制数量") @RequestParam(defaultValue = "10") Integer limit) {
        log.info("获取热门预约图书，开始日期：{}，结束日期：{}，限制数量：{}", startDate, endDate, limit);
        
        if (startDate == null) {
            startDate = LocalDate.now().minusMonths(1);
        }
        if (endDate == null) {
            endDate = LocalDate.now();
        }
        
        List<ReservationVO> result = reservationService.getHotReservedBooks(startDate, endDate, limit);
        return Result.success(result);
    }

    @GetMapping("/export")
    @Operation(summary = "导出预约记录", description = "导出预约记录到Excel文件")
    @PreAuthorize("hasAuthority('library:reservation:export')")
    public Result<String> exportReservations(@Valid ReservationQuery query) {
        log.info("导出预约记录，查询条件：{}", query);
        return reservationService.exportReservations(query);
    }
}
